package tresp.utils;

import java.util.TreeMap;
import java.util.Vector;

/**
 * 
 * <b>SymbolicPatternNode</b>
 * 
 * 
 * @author <font color="blue">Maxim Kirilov</font>
 *
 */
public class SymbolicPatternNode {
    
    
    public static final int maxlen = 30;
    public static final int seqlen = 2;
    public static final String iniseq = "**";
    private String value = null;
    private Vector<Integer> indexes = null;
    private TreeMap<String, SymbolicPatternNode> subnodes = null;

    
    public SymbolicPatternNode(String value) {
	indexes = new Vector<Integer>(); 
	subnodes = new TreeMap<String, SymbolicPatternNode>(); 
	this.value = value;
    }
    
    public boolean addSequenceAsynchronous(PatternAnalyzer inserter, String pattern, int idx){
	if ( inserter != null ){
	    inserter.add(this, pattern, idx);
	    return true;
	}
	return false;
    }
    public boolean addSequence(String pattern, int idx) {
	return addSequence(pattern, idx, 0);
    }

    private final boolean addSequence(String pattern, int idx, int level) {

	String q = pattern.substring(pattern.length() - 2);
	if (!q.equals(this.value)){ 
	    return false;
	}
	
	this.indexes.add( new Integer(idx) );

	if ((level >= 30) || (pattern.length() <= 2)) 
	    return true;

	String next = pattern.substring(0, pattern.length() - 2);
	q = next.substring(Math.max(next.length() - 2, 0));
	SymbolicPatternNode node = (SymbolicPatternNode)this.subnodes.get(q);

	if (node == null) { 
	    node = new SymbolicPatternNode(q); 
	    this.subnodes.put(q, node); 
	}
	return node.addSequence(next, idx, level + 1);
    }

    public Vector<Integer> getMatches(String pattern, int minmatches)
    {
	Vector<Integer> gotindexes = this.indexes;
	String next = pattern;
	boolean finish = false;
	do {
	    String q = next.substring(pattern.length() - 2);
	    if ((!q.equals(this.value)) || (this.indexes.size() < minmatches)) {
		finish = true;
	    }else
	    {
		next = next.substring(0, next.length() - 2);
		if (next.length() < 2) {
		    finish = true;
		} else {
		    q = next.substring(Math.max(next.length() - 2, 0));

		    SymbolicPatternNode node = (SymbolicPatternNode)this.subnodes.get(q);
		    if (node == null){
			finish = true;
		    }
		    else {
			gotindexes = node.getMatches(next, minmatches);
		    }
		}
	    }
	}while (!finish);
	
	return gotindexes;
    }
}
